#include "stdafx.h"
#include "Texture2D.h"
#include "GraphicsManager.h"

Texture2D::Texture2D(unsigned int width, unsigned int height, DXGI_FORMAT format, ID3D11Device*const device, D3D11_BIND_FLAG bindFlags, D3D11_CPU_ACCESS_FLAG cpu_access, D3D11_USAGE usage,
	void* existingdata, unsigned int structSize)
{
	GraphicsManager* pGraphics = GraphicsManager::GetInstance();
	if (device)
	{
		// create a texture 
		D3D11_TEXTURE2D_DESC tex_desc;
		ZeroMemory(&tex_desc, sizeof(D3D11_TEXTURE2D_DESC));

		tex_desc.ArraySize = 1;
		tex_desc.BindFlags = bindFlags;
		tex_desc.Format = format;
		tex_desc.Height = height;
		tex_desc.Width = width;
		tex_desc.MipLevels = 1;
		tex_desc.Usage = usage;
		tex_desc.SampleDesc.Count = 1;
		tex_desc.CPUAccessFlags = cpu_access;

		D3D11_SUBRESOURCE_DATA pResourceData;
		ZeroMemory(&pResourceData, sizeof(D3D11_SUBRESOURCE_DATA));

		pResourceData.pSysMem = existingdata;
		pResourceData.SysMemPitch = (width * height) * structSize;

		device->CreateTexture2D(&tex_desc, existingdata != nullptr ? &pResourceData : nullptr, &texture);
		device->CreateShaderResourceView(texture, nullptr, &srv);
	}
	else
	{
		// create a texture 
		D3D11_TEXTURE2D_DESC tex_desc;
		ZeroMemory(&tex_desc, sizeof(D3D11_TEXTURE2D_DESC));

		tex_desc.ArraySize = 1;
		tex_desc.BindFlags = bindFlags;
		tex_desc.Format = format;
		tex_desc.Height = height;
		tex_desc.Width = width;
		tex_desc.MipLevels = 1;
		tex_desc.Usage = usage;
		tex_desc.SampleDesc.Count = 1;
		tex_desc.CPUAccessFlags = cpu_access;

		pGraphics->getDevice()->CreateTexture2D(&tex_desc, nullptr, &texture);
		srv = pGraphics->createSRV(nullptr, (ID3D11Resource*)texture);
	}
}

Texture2D::Texture2D(ID3D11Texture2D* texture)
{
	this->texture = texture;

	GraphicsManager::GetInstance()->getDevice()->CreateShaderResourceView(texture, nullptr, &srv);
}

/*virtual*/ ID3D11ShaderResourceView* Texture2D::getSrv(void) const /*override*/
{
	return srv;
}

Texture2D::~Texture2D(void)
{
	texture->Release();
	if (srv)
		srv->Release();
}

void Texture2D::getData(void* data, unsigned int structSize)
{
	GraphicsManager* pgraphics = GraphicsManager::GetInstance();

	D3D11_MAPPED_SUBRESOURCE subresource;
	ZeroMemory(&subresource, sizeof(D3D11_MAPPED_SUBRESOURCE));

	pgraphics->getDeviceContext()->Map((ID3D11Resource*)texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &subresource);
	memcpy(subresource.pData, data, getWidth() * getHeight() * structSize);
	pgraphics->getDeviceContext()->Unmap(texture, 0);
}

void  Texture2D::setData(void* data, unsigned int structSize)
{
	GraphicsManager* pGraphics = GraphicsManager::GetInstance();

	D3D11_MAPPED_SUBRESOURCE subresource;
	ZeroMemory(&subresource, sizeof(D3D11_MAPPED_SUBRESOURCE));

	pGraphics->getDeviceContext()->Map(texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &subresource);
	memcpy(subresource.pData, data, getWidth() * getHeight() * structSize);
	pGraphics->getDeviceContext()->Unmap(texture, 0);
}